/**
 * Copyright (c) Huawei Technologies Co., Ltd. 2022. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */
#ifndef ENCLAVE_UTIL_H_
#define ENCLAVE_UTIL_H_
#include <error.h>
#include "logger.h"
#include "enclave.h"

#define CONNECT_NUM         10

enum {
    ENCLAVE_STOP,
    ENCLAVE_QUERY
};

struct cmd_msg {
    int cmd_type;
    union {
        int status;
        uint64_t enclave_id;
        struct enclave_instance_info info;
    } data;
};


#define QT_SUCCESS                          0  /* Perform a command successfully */
#define QT_MISSING_ARGS_ERROR               1  /* Missing necessary argument */
#define QT_INVALID_ARGS_ERROR               2  /* Invalid argument provided */
#define QT_FILE_OPS_ERROR                   3  /* File operation failure */
#define QT_IOCTL_GET_SANDBOX_CAP_ERROR      4  /* Ioctl get sandbox capacity failure */
#define QT_IOCTL_DEFINE_SANDBOX_ERROR       5  /* Ioctl define sandbox failure */
#define QT_INVALID_PARS_ERROR               6  /* Invalid parameters provided in configuration file */
#define QT_MISSING_ARGS_IN_CONF_ERROR       7  /* Missing necessary parameters in configuration file */
#define QT_MMAP_MEM_ERROR                   8  /* Mmap memory failure */
#define QT_IOCTL_ADD_MEM_ERROR              9  /* Ioctl add memory failure */
#define QT_LOAD_IMAGE_ERROR                 10 /* Load image failure because provided memory is too small */
#define QT_IOCTL_ADD_CPU_ERROR              11 /* Ioctl add cpu failure */
#define QT_LOCK_ACQUIRE_ERROR               12 /* Lock acquire failure */
#define QT_SOCKET_INIT_ERROR                13 /* Socket initialization failure */
#define QT_SOCKET_BIND_ERROR                14 /* Socket binding failure */
#define QT_SOCKET_LISTEN_ERROR              15 /* Socket listen failure */
#define QT_SOCKET_ACCEPT_ERROR              16 /* Socket accept failure */
#define QT_WRITE_HEARTBEAT_ERROR            17 /* Write heartbeat to the enclave failure */
#define QT_READ_HEARTBEAT_ERROR             18 /* Read heartbeat from the enclave failure */
#define QT_IOCTL_START_ERROR                19 /* Ioctl start an enclave failure */
#define QT_WAIT_HEARTBEAT_TIMEOUT_ERROR     20 /* Wait heartbeat timeout */
#define QT_GET_JSON_OBJ_ERROR               21 /* Get json print object failure */
#define QT_WRITE_ENCLAVE_CONFIG_ERROR       22 /* Write enclave's configuration file failure */
#define QT_SOCKET_CONNECT_ERROR             23 /* Socket connection failure */
#define QT_WRITE_CMD_TO_ENCLAVE_ERROR       24 /* Write cmd to the enclave server failure */
#define QT_READ_INFO_FROM_ENCLAVE_ERROR     25 /* Read message from the enclave server */
#define QT_CREATE_CJSON_OBJ_ERROR           26 /* Create cjson obj failure */
#define QT_CREATE_CJSON_ARR_ERROR           27 /* Create cjson array failure */
#define QT_ENCLAVE_NOT_RUNNING_ERROR        28 /* The required enclave is not running */
#define QT_INVALID_ENCLAVE_PID_ERROR        29 /* Invalid enclave pid */
#define QT_ADD_NUM_TO_CJSON_OBJ_ERROR       30 /* Add number into cjson object failure */
#define QT_ADD_STR_TO_CJSON_OBJ_ERROR       31 /* Add string into cjson object failure */
#define QT_NOT_IN_DEBUG_MODE_ERROR          32 /* The required enclave is not running in the debug mode */
#define QT_CONSOLE_READ_ERROR               33 /* Enclave console read failure */
#define QT_WRITE_IMG_HDR_ERROR              34 /* Write img header failure */
#define QT_WRITE_CMDLINE_ERROR              35 /* Write cmdline failure */
#define QT_WRITE_KERNEL_ERROR               36 /* Write kernel failure */
#define QT_WRITE_INITTRD_ERROR              37 /* Write initrd failure */
#define QT_WRITE_CERT_ERROR                 38 /* Write certificate failure */
#define QT_GET_PCR_ERROR                    39 /* Get pcr failure */
#define QT_ADD_SIG_ERROR                    40 /* Add signature failure */
#define QT_IMG_INFO_CHECK_ERROR             41 /* Check enclave image info failure while building an eif file */
#define QT_QTBOX_SANDBOX_OPS_ERROR          42 /* The required enclave is in maintenance state */
#define QT_UNDEINED_ERROR_NUM               -1 /* Not display errno */

#define VIRTIO_QTBOX_SANDBOX_VM_ERR_OPS_STATUS 283
#define VIRTIO_QTBOX_SANDBOX_VM_ERR_INSTANCE_NOSPC 259
/* a button to decide whether additional error info is displayed to the user */
typedef enum QT_DISPLAY_CHOICE {
    QT_DISPLAY_ADDITIONAL_ERROR,    /* Display additional error information to the user */
    QT_NOT_DISPLAY_ADDITIONAL_ERROR /* Display only EXX: ErroInfo to the user */
} qt_display_t;

typedef struct err_description_s {
    int err_num;
    char *err_description;
} err_description_t;

int serv_listen(const char *name);
int serv_accept(int listen_fd);
int cli_conn(const char *name);
void display_err_info(int err_num, const char *funcname, int linenr, qt_display_t flag, const char *fmt, ...);

#define log_debug(fmt, args...) enclave_log(LOG_DEBUG, __func__, __LINE__, fmt, ##args)
#define log_info(fmt, args...) enclave_log(LOG_INFO, __func__, __LINE__, fmt, ##args)
#define log_err(fmt, args...) enclave_log(LOG_ERR, __func__, __LINE__, fmt, ##args)
#define log_warn(fmt, args...) enclave_log(LOG_WARNING, __func__, __LINE__, fmt, ##args)
#define qt_log_err(err_num, flag, fmt, args...) do { \
    if (errno == VIRTIO_QTBOX_SANDBOX_VM_ERR_OPS_STATUS) \
        display_err_info(QT_QTBOX_SANDBOX_OPS_ERROR, __func__, __LINE__, flag, fmt, ##args); \
    else if (err_num > 0) \
        display_err_info(err_num, __func__, __LINE__, flag, fmt, ##args); \
    else \
        log_err(fmt, ##args); \
} while (0)
#endif